﻿#define Test_All

using Model;
using NLog;
using NLog.Config;
using System;
using System.Net;
using System.Text;
using System.Threading;

namespace App
{
    class Program
    {
        static void Main(string[] args)
        {
            LogManager.Configuration = new XmlLoggingConfiguration(AppDomain.CurrentDomain.BaseDirectory.ToString() + "/Config/NLog.config");
           StartServer(args);
        }

        private static void StartServer(string[] args)
        {
            // 所有异步回调到主线程中调用
            OneThreadSynchroniztionContext context = new OneThreadSynchroniztionContext();
            SynchronizationContext.SetSynchronizationContext(context);

            // 扫描程序集
            ObjectEvents.Instance.Add("App", typeof(Program).Assembly);
            ObjectEvents.Instance.Add("Model", DllHelper.GetCurrentAssembly());
            ObjectEvents.Instance.Add("Hotfix", DllHelper.GetHotfixAssembly());

            // 通过命令行把 启动的配置和服务类型 传递进来
            Options options = Game.Scene.AddComponent<OptionComponent, string[]>(args).Options;

#if Test_All
            options.AppType = AppType.All;
#endif

            // 根据命令行的配置文件进行 读取启动配置
            StartConfig startConfig = Game.Scene.AddComponent<StartConfigComponent, string, int>(options.Config, options.AppId).StartConfig;

            Game.Scene.AddComponent<ConfigComponent, string>(options.AppConfig);

            // 判断命令中的类型和 启动类型是否一致
            if (!options.AppType.Is(startConfig.AppType))
            {
                Log.Error("启动类型和配置中的类型不一致！");
                return;
            }

            LogManager.Configuration.Variables["appType"] = options.AppType.ToString();
            LogManager.Configuration.Variables["appId"] = options.AppId.ToString();

            // 添加操作码与类型对应的组件
            Game.Scene.AddComponent<OpcodeTypeComponent>();

            // 消息分发组件
            Game.Scene.AddComponent<MessageDispatcherComponent>();

            // 根据启动时传入的AppType类型进行启动不同的服务。
            switch (options.AppType)
            {
                case AppType.Manager:
                    Game.Scene.AddComponent<AppManagerComponent>();
                    break;
                case AppType.Realm:
                    Game.Scene.AddComponent<WebServiceComponent, string>($"http://{startConfig.InnerIP}");
                    break;
                case AppType.Gate:
                    Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(startConfig.GetInnerIP());
                    Game.Scene.AddComponent<NetOuterComponent, IPEndPoint>(startConfig.GetOuterIP());
                    break;
                case AppType.Game:
                    break;
                case AppType.DB:
                    string serverStr = Game.Scene.GetComponent<ConfigComponent>()["ConnStr"];
                    Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(startConfig.GetInnerIP());
                    Game.Scene.AddComponent<DBComponent, string>(serverStr);
                    break;
                case AppType.All:
                    //Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(startConfig.GetInnerIP());
                    //Game.Scene.AddComponent<NetOuterComponent, IPEndPoint>(startConfig.GetOuterIP());
                    // Game.Scene.AddComponent<TestComponent>();
                    Game.Scene.AddComponent<WebServiceComponent, string>(startConfig.GetServerIP());
                    //Game.Scene.AddComponent<DBComponent>();
                    //Game.Scene.AddComponent<HttpDataComponent, PlayType>(PlayType.KL8);
                    //Game.Scene.AddComponent<HttpDataComponent, PlayType>(PlayType.KL8, "Test");
                    break;
                default:
                    throw new Exception("没有对应的启动类型....");
            }

            Log.Info($"start server {options.AppType} ...");

            Console.Title = ConsoleTitleHelper.GetTitle(options, startConfig);

            while (true)
            {
                try
                {
                    Thread.Sleep(1);
                    context.Update();
                    ObjectEvents.Instance.Update();
                }
                catch (Exception e)
                {
                    Log.Error(e.Message);
                }
            }
        }
    }
}